<!DOCTYPE html>
<html lang="zh-CN">
<head hexo-theme='https://github.com/volantis-x/hexo-theme-volantis/tree/4.1.5'>
  <meta charset="utf-8">
  <!-- SEO相关 -->
  
    
  
  <!-- 渲染优化 -->
  <meta http-equiv='x-dns-prefetch-control' content='on' />
  <link rel='dns-prefetch' href='https://cdn.jsdelivr.net'>
  <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
  <meta name="renderer" content="webkit">
  <meta name="force-rendering" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <meta name="HandheldFriendly" content="True" >
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  <!-- 页面元数据 -->
  
  <title>EOS入门 - Schenk - Blog</title>
  
    <meta name="keywords" content="blockchain,eos">
  

  
    <meta name="description" content="EOS开发入门">
  

  <!-- feed -->
  

  <!-- import meta -->
  

  <!-- link -->
  
    <link rel="shortcut icon" type='image/x-icon' href="https://cdn.jsdelivr.net/gh/Schenk75/Source/logos/steroids.svg">
  

  <!-- import link -->
  

  
    
<link rel="stylesheet" href="/css/first.css">

  

  
  <link rel="stylesheet" href="/css/style.css" media="print" onload="this.media='all';this.onload=null">
  <noscript><link rel="stylesheet" href="/css/style.css"></noscript>
  

  <script id="loadcss"></script>

</head>

<body>
  

<header id="l_header" class="l_header auto shadow blur floatable show" style='opacity: 0' >
  <div class='container'>
  <div id='wrapper'>
    <div class='nav-sub'>
      <p class="title"></p>
      <ul class='switcher nav-list-h m-phone' id="pjax-header-nav-list">
        <li><a id="s-comment" class="fas fa-comments fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
          <li><a id="s-toc" class="s-toc fas fa-list fa-fw" target="_self" href='javascript:void(0)'></a></li>
        
      </ul>
    </div>
		<div class="nav-main">
      
        
        <a class="title flat-box" target="_self" href='/'>
          
            <img no-lazy class='logo' src='https://cdn.jsdelivr.net/gh/Schenk75/Source@latest/logos/taiga.svg'/>
          
          
          
        </a>
      

			<div class='menu navigation'>
				<ul class='nav-list-h m-pc'>
          
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
          
            
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
          
				</ul>
			</div>

      <div class="m_search">
        <form name="searchform" class="form u-search-form">
          <i class="icon fas fa-search fa-fw"></i>
          <input type="text" class="input u-search-input" placeholder="Search..." />
        </form>
      </div>

			<ul class='switcher nav-list-h m-phone'>
				
					<li><a class="s-search fas fa-search fa-fw" target="_self" href='javascript:void(0)'></a></li>
				
				<li>
          <a class="s-menu fas fa-bars fa-fw" target="_self" href='javascript:void(0)'></a>
          <ul class="menu-phone list-v navigation white-box">
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/
                  
                  
                  
                    id="home"
                  >
                  <i class='fab fa-stack-overflow fa-fw'></i>主页
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/categories/
                  
                  
                  
                    id="categories"
                  >
                  <i class='fas fa-folder-open fa-fw'></i>分类
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/tags/
                  
                  
                  
                    id="tags"
                  >
                  <i class='fas fa-tags fa-fw'></i>标签
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/archives/
                  
                  
                  
                    id="archives"
                  >
                  <i class='fas fa-archive fa-fw'></i>归档
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/friends/
                  
                  
                  
                    id="friends"
                  >
                  <i class='fas fa-link fa-fw'></i>友链
                </a>
                
              </li>
            
          
            
              
            
              <li>
                <a class="menuitem flat-box faa-parent animated-hover" href=/about/
                  
                  
                  
                    id="about"
                  >
                  <i class='fas fa-info-circle fa-fw'></i>关于
                </a>
                
              </li>
            
          
            
          </ul>
        </li>
			</ul>
		</div>
	</div>
  </div>
</header>

  <div id="l_body">
    <div id="l_cover">
  
    
        <div id="full" class='cover-wrapper post dock' style="display: none;">
          
            <div class='cover-bg lazyload placeholder' data-bg="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/interstellar.jpg"></div>
          
          <div class='cover-body'>
  <div class='top'>
    
    
      <p class="title">Schenk - Blog</p>
    
    
      <p class="subtitle">SJTUer | Cuber</p>
    
  </div>
  <div class='bottom'>
    <div class='menu navigation'>
      <div class='list-h'>
        
          
            <a href="/categories/"
              
              
              id="categories">
              <i class='fas fa-folder-open fa-fw'></i><p>分类</p>
            </a>
          
            <a href="/tags/"
              
              
              id="tags">
              <i class='fas fa-tags fa-fw'></i><p>标签</p>
            </a>
          
            <a href="/archives/"
              
              
              id="archives">
              <i class='fas fa-archive fa-fw'></i><p>归档</p>
            </a>
          
            <a href="/friends/"
              
              
              id="friends">
              <i class='fas fa-link fa-fw'></i><p>友链</p>
            </a>
          
            <a href="/about/"
              
              
              id="about">
              <i class='fas fa-info-circle fa-fw'></i><p>关于</p>
            </a>
          
        
      </div>
    </div>
  </div>
</div>

          <div id="scroll-down" style="display: none;"><i class="fa fa-chevron-down scroll-down-effects"></i></div>
        </div>
    
  
  </div>

    <div id='safearea'>
      <div class='body-wrapper' id="pjax-container">
        

<div class='l_main'>
  <article class="article post white-box reveal md shadow floatable article-type-post" id="post" itemscope itemprop="blogPost">
  


  
  <div class="article-meta" id="top">
    
    
    
      <h1 class="title">
        EOS入门
      </h1>
      <div class='new-meta-box'>
        
          
            
<div class='new-meta-item author'>
  <a class='author' href="/" rel="nofollow">
    <img no-lazy src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/common/avatar.jpg">
    <p>Schenk</p>
  </a>
</div>

          
        
          
            
  <div class='new-meta-item category'>
    <a class='notlink'>
      <i class="fas fa-folder-open fa-fw" aria-hidden="true"></i>
      <a class="category-link" href="/categories/Notes/">Notes</a>
    </a>
  </div>


          
        
          
            <div class="new-meta-item date" itemprop="dateUpdated" datetime="2022-04-28T15:47:46+08:00">
  <a class='notlink'>
    <i class="fas fa-edit fa-fw" aria-hidden="true"></i>
    <p>更新于：2022年4月28日</p>
  </a>
</div>

          
        
          
            
  <div class="new-meta-item wordcount">
    <a class='notlink'>
      <i class="fas fa-keyboard fa-fw" aria-hidden="true"></i>
      <p>字数：2.6k字</p>
    </a>
  </div>
  <div class="new-meta-item readtime">
    <a class='notlink'>
      <i class="fas fa-hourglass-half fa-fw" aria-hidden="true"></i>
      <p>时长：11分钟</p>
    </a>
  </div>


          
        
          
            
  <div class="new-meta-item browse leancloud">
    <a class='notlink'>
      
      <div id="lc-pv" data-title="EOS入门" data-path="/2021/04/09/learning-notes/eos%E5%85%A5%E9%97%A8/">
        <i class="fas fa-eye fa-fw" aria-hidden="true"></i>
        <span id='number'><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span>
        次浏览
      </div>
    </a>
  </div>


          
        
      </div>
    
  </div>


  
  <p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/eos%E5%85%A5%E9%97%A8/1-1Z11115143O34.gif" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/eos%E5%85%A5%E9%97%A8/1-1Z11115143O34.gif" srcset="" alt="比特币、以太坊、EOS的对比"></p>
<h2 id="简介">简介</h2>
<h3 id="平台和工具链">平台和工具链</h3>
<p><img src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/eos%E5%85%A5%E9%97%A8/EOSIO-Overview-dev.svg" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/notes/eos%E5%85%A5%E9%97%A8/EOSIO-Overview-dev.svg" srcset="" alt="EOSIO Development Lifecycle"></p>
<h4 id="Nodeos">Nodeos</h4>
<ul>
<li>EOSIO节点守护进程的核心</li>
<li>处理区块链数据持久层、点对点网络和智能合约调度</li>
<li>在开发环境中，可以使用nodeos建立单节点区块链网络</li>
</ul>
<h4 id="Cleos">Cleos</h4>
<ul>
<li>命令行工具，调用nodeos暴露的接口API</li>
<li>部署和测试EOSIO智能合约</li>
</ul>
<h4 id="Keosd">Keosd</h4>
<ul>
<li>密钥管理器守护进程，用于存储私钥和对消息签名</li>
<li>keosd为要在相关钱包文件中加密的密钥提供安全密钥存储介质</li>
<li>keosd守护进程还定义了一个安全的enclave，用于对cleos或第三方库创建的交易进行签名</li>
</ul>
<h4 id="EOSIO-CDT">EOSIO.CDT</h4>
<ul>
<li>WASM工具链</li>
<li>对EOSIO智能合约的编译进行EOSIO-specfic优化</li>
</ul>
<h4 id="EOSJS">EOSJS</h4>
<ul>
<li>JavaScript API SDK，集成基于EOSIO的区块链</li>
</ul>
<h3 id="核心概念">核心概念</h3>
<h4 id="账户">账户</h4>
<ul>
<li>存储在区块链上的人类可读的名字</li>
<li>用于转移或提交有效的交易到区块链上</li>
</ul>
<h4 id="钱包">钱包</h4>
<ul>
<li>存储密钥的客户端</li>
<li>理想情况下，钱包有一个加密状态和一个解密状态</li>
</ul>
<h4 id="授权和权限">授权和权限</h4>
<ul>
<li>定义交易的需求，通过linking authorization或linkauth来为特殊合约分配权限</li>
</ul>
<h4 id="智能合约">智能合约</h4>
<ul>
<li>在链上执行，一旦执行就永久留存在链上且不可变</li>
</ul>
<h4 id="DPOS共识">DPOS共识</h4>
<ul>
<li>Delegated Proof of Stake 委托权益证明</li>
<li>若在链上持有token，可以通过投票系统选择block producer</li>
<li>任何人都可以参与block producer的竞选</li>
</ul>
<h4 id="RAM">RAM</h4>
<ul>
<li>被视为永久存储，用于存放账户名、权限、代币余额等需要快速访问的链上数据</li>
<li>RAM需要购买，并且不是基于权益分配，因为RAM是一个有限的持久性资源</li>
</ul>
<h4 id="CPU">CPU</h4>
<ul>
<li>代表区块链上一个动作的执行时间</li>
<li>在cleos的 <code>get account</code> 命令的输出中，CPU被称为 <code>cpu bandwidth</code>，代表一个账户在将动作提交到合约时可以支配的处理时间</li>
<li>CPU是一个瞬态系统资源，属于EOSIO的权益机制</li>
</ul>
<h4 id="NET">NET</h4>
<ul>
<li>NET是交易的网络带宽，单位为byte</li>
<li>在cleos的 <code>get account</code> 命令的输出中，NET被称为 <code>net bandwidth</code></li>
<li>NET是一个瞬态系统资源，属于EOSIO的权益机制</li>
</ul>
<h3 id="技术特征">技术特征</h3>
<h4 id="WebAssembly-C-编译">WebAssembly C++编译</h4>
<ul>
<li>EOSIO使用C++编写智能合约</li>
<li>在EOSIO核心层的顶端是一个Wasm虚拟机：<code>EOS VM</code> ，用于执行智能合约（它是为区块链应用的高要求而设计的，对WebAssembly引擎的要求远远高于为web浏览器标准开发而设计的引擎）</li>
<li>使用Wasm标准有利于将其他语言移植到EOSIO平台</li>
</ul>
<h4 id="高吞吐量、更快的确认、低延迟">高吞吐量、更快的确认、低延迟</h4>
<h4 id="通过智能合约分配和管理资源">通过智能合约分配和管理资源</h4>
<h4 id="权益机制">权益机制</h4>
<ul>
<li>通过权益机制来获取系统资源（CPU和NET）</li>
<li>用户使用权益token换取CPU和NET的使用，按照占所有用户的token比例分配</li>
</ul>
<h4 id="商业模型灵活性">商业模型灵活性</h4>
<h4 id="综合的权限架构">综合的权限架构</h4>
<h4 id="可升级">可升级</h4>
<h4 id="高效能源消耗">高效能源消耗</h4>
<h2 id="环境配置">环境配置</h2>
<h3 id="安装EOSIO和CDT">安装EOSIO和CDT</h3>
<p>根据<a target="_blank" rel="noopener" href="https://developers.eos.io/welcome/latest/getting-started-guide/local-development-environment/index">官网指示</a>安装<a target="_blank" rel="noopener" href="https://github.com/EOSIO/eos/releases">EOSIO</a>和<a target="_blank" rel="noopener" href="https://github.com/eosio/eosio.cdt/releases">CDT</a>，在Ubuntu20.04上，下载github上对应的Pre-release包</p>
<h3 id="创建开发钱包">创建开发钱包</h3>
<h4 id="创建钱包">创建钱包</h4>
<p>注意保存密码</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos wallet create --to-console</span><br></pre></td></tr></table></figure>
<h4 id="打开钱包">打开钱包</h4>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos wallet open</span><br></pre></td></tr></table></figure>
<p>查看钱包列表</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos wallet list</span><br></pre></td></tr></table></figure>
<h4 id="解锁钱包">解锁钱包</h4>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos wallet unlock</span><br></pre></td></tr></table></figure>
<h4 id="向钱包导入密钥">向钱包导入密钥</h4>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos wallet create_key</span><br></pre></td></tr></table></figure>
<h4 id="导入开发密钥">导入开发密钥</h4>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos wallet import</span><br></pre></td></tr></table></figure>
<p>输入如下私钥（所有新的EOSIO链都有相同的开发密钥）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3</span><br></pre></td></tr></table></figure>
<p>对应的开发公钥为：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV</span><br></pre></td></tr></table></figure>
<h3 id="开启keosd和nodeos">开启keosd和nodeos</h3>
<h4 id="开启keosd">开启keosd</h4>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">keosd &amp;</span><br></pre></td></tr></table></figure>
<p>若遇到报错：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;3120000 wallet_exception: Wallet exception Failed to lock access to wallet directory; is another keosd running?&quot;</span></span><br></pre></td></tr></table></figure>
<p>先使用命令 <code>pkill keosd</code> 再重新开启</p>
<h4 id="开启nodeos">开启nodeos</h4>
<p>运行Nodeos，加载所有基本插件，设置服务器地址，开启CORS，添加合约debug和日志</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">nodeos -e -p eosio \</span><br><span class="line">--plugin eosio::producer_plugin \</span><br><span class="line">--plugin eosio::producer_api_plugin \</span><br><span class="line">--plugin eosio::chain_api_plugin \</span><br><span class="line">--plugin eosio::http_plugin \</span><br><span class="line">--plugin eosio::history_plugin \</span><br><span class="line">--plugin eosio::history_api_plugin \</span><br><span class="line">--filter-on=<span class="string">&quot;*&quot;</span> \</span><br><span class="line">--access-control-allow-origin=<span class="string">&#x27;*&#x27;</span> \</span><br><span class="line">--contracts-console \</span><br><span class="line">--http-validate-host=<span class="literal">false</span> \</span><br><span class="line">--verbose-http-errors &gt;&gt; nodeos.log 2&gt;&amp;1 &amp;</span><br></pre></td></tr></table></figure>
<h4 id="查看日志">查看日志</h4>
<p>查看Nodeos是否正在出块</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tail -f nodeos.log</span><br></pre></td></tr></table></figure>
<p>如果报错 <code>Database dirty flag set (likely due to unclean shutdown): replay required</code> ，先使用命令 <code>pkill nodeos</code> 安全关闭nodeos，再重新开启</p>
<h4 id="确保RPC-API正常运行">确保RPC API正常运行</h4>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl http://localhost:8888/v1/chain/get_info</span><br></pre></td></tr></table></figure>
<h3 id="创建开发账户">创建开发账户</h3>
<ul>
<li>账户是授权的集合，保存在区块链上</li>
<li>账户可以标识一个用户，也可以标识智能合约（一个账户只能有一个智能合约）</li>
<li>账户可以由一个用户或一组用户控制</li>
</ul>
<h4 id="创建测试账户">创建测试账户</h4>
<p>每个EOSIO账户都和一个公钥绑定</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cleos create account eosio bob EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV</span><br><span class="line"></span><br><span class="line">cleos create account eosio alice EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV</span><br></pre></td></tr></table></figure>
<h4 id="查看账户信息">查看账户信息</h4>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos get account alice</span><br></pre></td></tr></table></figure>
<p>得到如下结果：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">permissions: </span><br><span class="line">     owner     1:    1 EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV</span><br><span class="line">        active     1:    1 EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV</span><br><span class="line">memory: </span><br><span class="line">     quota:       unlimited  used:      2.66 KiB  </span><br><span class="line"></span><br><span class="line">net bandwidth: </span><br><span class="line">     used:               unlimited</span><br><span class="line">     available:          unlimited</span><br><span class="line">     <span class="built_in">limit</span>:              unlimited</span><br><span class="line"></span><br><span class="line">cpu bandwidth:</span><br><span class="line">     used:               unlimited</span><br><span class="line">     available:          unlimited</span><br><span class="line">     <span class="built_in">limit</span>:              unlimited</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>用户可以暴露active公钥，自己保存owner公钥，这样，如果active公钥被泄露，用户可以使用owner公钥取回账户控制权（所以建议使用不同的active公钥和owner公钥）</p>
<h2 id="智能合约编写">智能合约编写</h2>
<h3 id="Hello-World">Hello World</h3>
<ol>
<li>
<p>创建hello目录并编写hello.cpp</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;eosio/eosio.hpp&gt;</span></span></span><br><span class="line"><span class="class"><span class="keyword">class</span> [[<span class="title">eosio</span>:</span>:contract]] hello : <span class="keyword">public</span> eosio::contract &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">using</span> eosio::contract::contract;</span><br><span class="line">    [[eosio::action]] <span class="function"><span class="keyword">void</span> <span class="title">hi</span><span class="params">(eosio::name user)</span> </span>&#123;</span><br><span class="line">        print(<span class="string">&quot;Hello, &quot;</span>, user);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>编译cpp，会产生两个文件：hello.wasm和hello.abi</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">eosio-cpp -abigen -o hello.wasm hello.cpp</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>部署智能合约</p>
<ul>
<li>
<p>首先创建一个新的hello账户，在hello目录下生成hello账户的公私钥</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos create key --file hello_key</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>使用生成的公钥创建hello账户</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos create account eosio hello &lt;public key&gt;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>向钱包导入hello私钥</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos wallet import</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>部署hello智能合约到hello账户（先cd到contracts目录）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos <span class="built_in">set</span> contract hello ./hello -p hello@active</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li>
<p>调用智能合约</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos push action hello hi <span class="string">&#x27;[&quot;bob&quot;]&#x27;</span> -p bob@active</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>设置智能合约调用权限</p>
<ul>
<li>
<p>修改hello.cpp并重新编译以及部署</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;eosio/eosio.hpp&gt;</span></span></span><br><span class="line"><span class="class"><span class="keyword">class</span> [[<span class="title">eosio</span>:</span>:contract]] hello : <span class="keyword">public</span> eosio::contract &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">using</span> eosio::contract::contract;</span><br><span class="line">    [[eosio::action]] <span class="function"><span class="keyword">void</span> <span class="title">hi</span><span class="params">(eosio::name user)</span> </span>&#123;</span><br><span class="line">        require_auth(user);</span><br><span class="line">        print(<span class="string">&quot;Hello, &quot;</span>, eosio::name&#123; user &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>测试：bob说hi，但交易由alice签名（失败）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cleos push action hello hi <span class="string">&#x27;[&quot;bob&quot;]&#x27;</span> -p alice@active</span><br><span class="line"></span><br><span class="line">Error 3090004: Missing required authority</span><br><span class="line">Ensure that you have the related authority inside your transaction!;</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>测试：bob说hi，交易由bob签名（成功）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cleos push action hello hi <span class="string">&#x27;[&quot;bob&quot;]&#x27;</span> -p bob@active</span><br><span class="line"></span><br><span class="line">executed transaction: 033b54bd4a79a9bc868910087bd769e108ffe6f0db29b2b51c61007b03880f51  104 bytes  116 us</span><br><span class="line"><span class="comment">#         hello &lt;= hello::hi                    &#123;&quot;user&quot;:&quot;bob&quot;&#125;</span></span><br><span class="line">&gt;&gt; Hello, bob</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ol>
<h3 id="Tokens">Tokens</h3>
<ol>
<li>
<p>获取源代码，在contracts目录下：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/EOSIO/eosio.contracts --branch v1.7.0 --single-branch</span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> eosio.contracts/contracts/eosio.token</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>创建一个账户来部署token合约（公钥是EOSIO开发公钥）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos create account eosio eosio.token EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>编译智能合约</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">eosio-cpp -I include -o eosio.token.wasm src/eosio.token.cpp --abigen</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>部署智能合约（cd到 <em>eosio.token/…/</em> 目录下）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos <span class="built_in">set</span> contract eosio.token ./eosio.token --abi eosio.token.abi -p eosio.token@active</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>创建token：需要指定一个颁发者和token名称以及最大供应量；同时为了创建token，需要eosio.token账户的权限</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos push action eosio.token create <span class="string">&#x27;[ &quot;alice&quot;, &quot;1000000000.0000 SYS&quot;]&#x27;</span> -p eosio.token@active</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>颁发token：拥有颁发权的alice颁发100个token（可以加上 <code>-d -j</code> 参数来debug）</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos push action eosio.token issue <span class="string">&#x27;[ &quot;alice&quot;, &quot;100.0000 SYS&quot;, &quot;memo&quot; ]&#x27;</span> -p alice@active</span><br></pre></td></tr></table></figure>
</li>
<li>
<p>交易token：alice转了25个token给bob</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cleos push action eosio.token transfer <span class="string">&#x27;[ &quot;alice&quot;, &quot;bob&quot;, &quot;25.0000 SYS&quot;, &quot;m&quot; ]&#x27;</span> -p alice@active</span><br></pre></td></tr></table></figure>
<ul>
<li>
<p>查看bob以及alice的账户余额</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cleos get currency balance eosio.token bob SYS</span><br><span class="line"></span><br><span class="line">cleos get currency balance eosio.token alice SYS</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ol>
<h3 id="ABI文件">ABI文件</h3>
<p>Application Binary Interface（ABI）用来描述如何将用户操作在JSON格式和二进制格式之间转换</p>
<blockquote>
<p>ABI文件结构</p>
</blockquote>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">   <span class="attr">&quot;version&quot;</span>: <span class="string">&quot;eosio::abi/1.0&quot;</span>,</span><br><span class="line">   <span class="attr">&quot;types&quot;</span>: [],</span><br><span class="line">   <span class="attr">&quot;structs&quot;</span>: [],</span><br><span class="line">   <span class="attr">&quot;actions&quot;</span>: [],</span><br><span class="line">   <span class="attr">&quot;tables&quot;</span>: [],</span><br><span class="line">   <span class="attr">&quot;ricardian_clauses&quot;</span>: [],</span><br><span class="line">   <span class="attr">&quot;abi_extensions&quot;</span>: [],</span><br><span class="line">   <span class="attr">&quot;___comment&quot;</span> : <span class="string">&quot;&quot;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="types">types</h4>
<p><strong>自定义数据类型</strong>需要在ABI文件中进行描述，但是对于EOS.IO的内建类型，无需在ABI文件中说明，之前的<code>hello</code>和<code>eos.token</code>合约的ABI文件中，<code>types</code>都是<code>[]</code>，因为没有自定义类型</p>
<p>如下，给<code>account_name</code>建立一个笔名，在ABI文件里用<code>name</code>可以代替<code>account_name</code></p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&quot;types&quot;: [&#123;</span><br><span class="line">    &quot;new_type_name&quot;: &quot;account_name&quot;,</span><br><span class="line">    &quot;type&quot;: &quot;name&quot;</span><br><span class="line">&#125;]</span><br></pre></td></tr></table></figure>
<h4 id="structs">structs</h4>
<p>声明各个<code>action</code>需要传入的参数，系统根据<code>actions</code>部分中声明的<code>type</code>，在<code>structs</code>部分寻找对应的数据结构，也就是说，函数声明部分并没包含具体内容，具体数据需要到<code>structs</code>中寻找</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">   <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;issue&quot;</span>,  	<span class="comment">// 数据结构名</span></span><br><span class="line">   <span class="attr">&quot;base&quot;</span>: <span class="string">&quot;&quot;</span>, 			<span class="comment">// 继承的父结构名</span></span><br><span class="line">   <span class="attr">&quot;fields&quot;</span>: [			<span class="comment">// 参数数组，包含参数名和类型</span></span><br><span class="line">       &#123;<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;&quot;</span>, <span class="attr">&quot;type&quot;</span>:<span class="string">&quot;&quot;</span>&#125;,</span><br><span class="line">   ]			</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>例子：</p>
<figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">&quot;structs&quot;: [&#123;</span><br><span class="line">      &quot;name&quot;: &quot;transfer&quot;,</span><br><span class="line">      &quot;base&quot;: &quot;&quot;,</span><br><span class="line">      &quot;fields&quot;: [</span><br><span class="line">        &#123;&quot;name&quot;:&quot;from&quot;, &quot;type&quot;:&quot;account_name&quot;&#125;,</span><br><span class="line">        &#123;&quot;name&quot;:&quot;to&quot;, &quot;type&quot;:&quot;account_name&quot;&#125;,</span><br><span class="line">        &#123;&quot;name&quot;:&quot;quantity&quot;, &quot;type&quot;:&quot;asset&quot;&#125;,</span><br><span class="line">        &#123;<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;memo&quot;</span>, <span class="attr">&quot;type&quot;</span>:<span class="string">&quot;string&quot;</span>&#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;,&#123;</span><br><span class="line">     &quot;name&quot;: &quot;create&quot;,</span><br><span class="line">     &quot;base&quot;: &quot;&quot;,</span><br><span class="line">     &quot;fields&quot;: [</span><br><span class="line">        &#123;&quot;name&quot;:&quot;issuer&quot;, &quot;type&quot;:&quot;account_name&quot;&#125;,</span><br><span class="line">        &#123;&quot;name&quot;:&quot;maximum_supply&quot;, &quot;type&quot;:&quot;asset&quot;&#125;,</span><br><span class="line">        &#123;&quot;name&quot;:&quot;can_freeze&quot;, &quot;type&quot;:&quot;uint8&quot;&#125;,</span><br><span class="line">        &#123;&quot;name&quot;:&quot;can_recall&quot;, &quot;type&quot;:&quot;uint8&quot;&#125;,</span><br><span class="line">        &#123;<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;can_whitelist&quot;</span>, <span class="attr">&quot;type&quot;</span>:<span class="string">&quot;uint8&quot;</span>&#125;</span><br><span class="line">     ]</span><br><span class="line">  &#125;,&#123;</span><br><span class="line">     &quot;name&quot;: &quot;issue&quot;,</span><br><span class="line">     &quot;base&quot;: &quot;&quot;,</span><br><span class="line">     &quot;fields&quot;: [</span><br><span class="line">        &#123;&quot;name&quot;:&quot;to&quot;, &quot;type&quot;:&quot;account_name&quot;&#125;,</span><br><span class="line">        &#123;&quot;name&quot;:&quot;quantity&quot;, &quot;type&quot;:&quot;asset&quot;&#125;,</span><br><span class="line">        &#123;<span class="attr">&quot;name&quot;</span>:<span class="string">&quot;memo&quot;</span>, <span class="attr">&quot;type&quot;</span>:<span class="string">&quot;string&quot;</span>&#125;</span><br><span class="line">     ]</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
<h4 id="actions">actions</h4>
<p>用于声明智能合约有哪些可以调用的<code>action</code></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;transfer&quot;</span>, 			<span class="comment">// 在智能合约中定义的函数名</span></span><br><span class="line">  <span class="attr">&quot;type&quot;</span>: <span class="string">&quot;transfer&quot;</span>, 			<span class="comment">// 在structs中声明的数据结构名</span></span><br><span class="line">  <span class="attr">&quot;ricardian_contract&quot;</span>: <span class="string">&quot;&quot;</span> 	<span class="comment">// 可选参数，开发中</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="tables">tables</h4>
<p>列出智能合约需要建立的<strong>数据表的名称</strong>以及数据表中存储的结构体名称</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;&quot;</span>,       <span class="comment">// 数据表的名称</span></span><br><span class="line">  <span class="attr">&quot;type&quot;</span>: <span class="string">&quot;&quot;</span>,       <span class="comment">// 数据表对应的struct</span></span><br><span class="line">  <span class="attr">&quot;index_type&quot;</span>: <span class="string">&quot;&quot;</span>, <span class="comment">// 主键类型</span></span><br><span class="line">  <span class="attr">&quot;key_names&quot;</span> : [], <span class="comment">// 键名列表，长度与key_types相同</span></span><br><span class="line">  <span class="attr">&quot;key_types&quot;</span> : []  <span class="comment">// 键的类型列表，长度与key_names相同</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>例子：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">&quot;name&quot;</span>: <span class="string">&quot;accounts&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;type&quot;</span>: <span class="string">&quot;account&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;index_type&quot;</span>: <span class="string">&quot;i64&quot;</span>,</span><br><span class="line">  <span class="attr">&quot;key_names&quot;</span> : [<span class="string">&quot;primary_key&quot;</span>],</span><br><span class="line">  <span class="attr">&quot;key_types&quot;</span> : [<span class="string">&quot;uint64&quot;</span>]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

  
  
    
    <div class='footer'>
      
      
      
      
    </div>
  
  
    


  <div class='article-meta' id="bottom">
    <div class='new-meta-box'>
      
        
          <div class="new-meta-item date">
  <a class='notlink'>
    <i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i>
    <p>发布于：2021年4月9日</p>
  </a>
</div>

        
      
        
          
  
  <div class="new-meta-item meta-tags"><a class="tag" href="/tags/blockchain/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>blockchain</p></a></div> <div class="new-meta-item meta-tags"><a class="tag" href="/tags/eos/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>eos</p></a></div>


        
      
    </div>
  </div>


  
  

  
    <div class="prev-next">
      
        <a class='prev' href='/2021/04/12/paper-reading/paper-twine/'>
          <p class='title'><i class="fas fa-chevron-left" aria-hidden="true"></i>论文阅读-TWINE An Embedded Trusted Runtime</p>
          <p class='content'>1.Introduction
TWINE（Trusted Wasm in Enclave）

使用标准Intel工具链实现
允许本地执行遗留Wasm应用程序，而无需重新编译
动态地将WASI操作...</p>
        </a>
      
      
        <a class='next' href='/2021/03/24/learning-notes/rust-advance/'>
          <p class='title'>Rust高级特性<i class="fas fa-chevron-right" aria-hidden="true"></i></p>
          <p class='content'>闭包
在函数中返回闭包：


为了从函数返回一些东西，Rust 需要知道返回类型的大小，而不能直接返回一个trait，因此可以返回一个Box指针


在函数中定义的变量放入闭包中返回，会因为移出...</p>
        </a>
      
    </div>
  
</article>


  

  






</div>
<aside class='l_side'>
  
  
    
    



  <section class="widget toc-wrapper shadow floatable desktop mobile" id="toc-div" >
    
  <header>
    
      <i class="fas fa-list fa-fw" aria-hidden="true"></i><span class='name'>本文目录</span>
    
  </header>


    <div class='content'>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%AE%80%E4%BB%8B"><span class="toc-text">简介</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%B9%B3%E5%8F%B0%E5%92%8C%E5%B7%A5%E5%85%B7%E9%93%BE"><span class="toc-text">平台和工具链</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Nodeos"><span class="toc-text">Nodeos</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Cleos"><span class="toc-text">Cleos</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Keosd"><span class="toc-text">Keosd</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EOSIO-CDT"><span class="toc-text">EOSIO.CDT</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#EOSJS"><span class="toc-text">EOSJS</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5"><span class="toc-text">核心概念</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%B4%A6%E6%88%B7"><span class="toc-text">账户</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%92%B1%E5%8C%85"><span class="toc-text">钱包</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%8E%88%E6%9D%83%E5%92%8C%E6%9D%83%E9%99%90"><span class="toc-text">授权和权限</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6"><span class="toc-text">智能合约</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#DPOS%E5%85%B1%E8%AF%86"><span class="toc-text">DPOS共识</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RAM"><span class="toc-text">RAM</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#CPU"><span class="toc-text">CPU</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#NET"><span class="toc-text">NET</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8A%80%E6%9C%AF%E7%89%B9%E5%BE%81"><span class="toc-text">技术特征</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#WebAssembly-C-%E7%BC%96%E8%AF%91"><span class="toc-text">WebAssembly C++编译</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%AB%98%E5%90%9E%E5%90%90%E9%87%8F%E3%80%81%E6%9B%B4%E5%BF%AB%E7%9A%84%E7%A1%AE%E8%AE%A4%E3%80%81%E4%BD%8E%E5%BB%B6%E8%BF%9F"><span class="toc-text">高吞吐量、更快的确认、低延迟</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%80%9A%E8%BF%87%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6%E5%88%86%E9%85%8D%E5%92%8C%E7%AE%A1%E7%90%86%E8%B5%84%E6%BA%90"><span class="toc-text">通过智能合约分配和管理资源</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9D%83%E7%9B%8A%E6%9C%BA%E5%88%B6"><span class="toc-text">权益机制</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%95%86%E4%B8%9A%E6%A8%A1%E5%9E%8B%E7%81%B5%E6%B4%BB%E6%80%A7"><span class="toc-text">商业模型灵活性</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%BB%BC%E5%90%88%E7%9A%84%E6%9D%83%E9%99%90%E6%9E%B6%E6%9E%84"><span class="toc-text">综合的权限架构</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%AF%E5%8D%87%E7%BA%A7"><span class="toc-text">可升级</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%AB%98%E6%95%88%E8%83%BD%E6%BA%90%E6%B6%88%E8%80%97"><span class="toc-text">高效能源消耗</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE"><span class="toc-text">环境配置</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AE%89%E8%A3%85EOSIO%E5%92%8CCDT"><span class="toc-text">安装EOSIO和CDT</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E5%BC%80%E5%8F%91%E9%92%B1%E5%8C%85"><span class="toc-text">创建开发钱包</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E9%92%B1%E5%8C%85"><span class="toc-text">创建钱包</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%89%93%E5%BC%80%E9%92%B1%E5%8C%85"><span class="toc-text">打开钱包</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%A7%A3%E9%94%81%E9%92%B1%E5%8C%85"><span class="toc-text">解锁钱包</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%90%91%E9%92%B1%E5%8C%85%E5%AF%BC%E5%85%A5%E5%AF%86%E9%92%A5"><span class="toc-text">向钱包导入密钥</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%BC%E5%85%A5%E5%BC%80%E5%8F%91%E5%AF%86%E9%92%A5"><span class="toc-text">导入开发密钥</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%BC%80%E5%90%AFkeosd%E5%92%8Cnodeos"><span class="toc-text">开启keosd和nodeos</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%80%E5%90%AFkeosd"><span class="toc-text">开启keosd</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%80%E5%90%AFnodeos"><span class="toc-text">开启nodeos</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9F%A5%E7%9C%8B%E6%97%A5%E5%BF%97"><span class="toc-text">查看日志</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%A1%AE%E4%BF%9DRPC-API%E6%AD%A3%E5%B8%B8%E8%BF%90%E8%A1%8C"><span class="toc-text">确保RPC API正常运行</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E5%BC%80%E5%8F%91%E8%B4%A6%E6%88%B7"><span class="toc-text">创建开发账户</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E6%B5%8B%E8%AF%95%E8%B4%A6%E6%88%B7"><span class="toc-text">创建测试账户</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9F%A5%E7%9C%8B%E8%B4%A6%E6%88%B7%E4%BF%A1%E6%81%AF"><span class="toc-text">查看账户信息</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6%E7%BC%96%E5%86%99"><span class="toc-text">智能合约编写</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Hello-World"><span class="toc-text">Hello World</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Tokens"><span class="toc-text">Tokens</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#ABI%E6%96%87%E4%BB%B6"><span class="toc-text">ABI文件</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#types"><span class="toc-text">types</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#structs"><span class="toc-text">structs</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#actions"><span class="toc-text">actions</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#tables"><span class="toc-text">tables</span></a></li></ol></li></ol></li></ol>
    </div>
  </section>


  


</aside>



        
        
          <!--此文件用来存放一些不方便取值的变量-->
<!--思路大概是将值藏到重加载的区域内-->

<script>
  window.pdata={}
  pdata.ispage=true;
  pdata.postTitle="EOS入门";
  pdata.commentPath="";
  pdata.commentPlaceholder="";

  var l_header=document.getElementById("l_header");
  
  l_header.classList.add("show");
  
</script>

        
      </div>
      
  
  <footer class="footer clearfix">
    <br><br>
    
      
        <div class='copyright'>
        <p><a target="_blank" rel="noopener" href="https://github.com/Schenk75/Schenk75.github.io">Copyright © 2020-2022 Schenk</a></p>

        </div>
      
    
  </footer>


      <a id="s-top" class="fas fa-arrow-up fa-fw" href='javascript:void(0)'></a>
    </div>
  </div>
  <div>
    <script>
window.volantis={};
window.volantis.loadcss=document.getElementById("loadcss");
/********************脚本懒加载函数********************************/
function loadScript(src, cb) {
var HEAD = document.getElementsByTagName('head')[0] || document.documentElement;
var script = document.createElement('script');
script.setAttribute('type','text/javascript');
if (cb) script.onload = cb;
script.setAttribute('src', src);
HEAD.appendChild(script);
}
//https://github.com/filamentgroup/loadCSS
var loadCSS = function( href, before, media, attributes ){
	var doc = window.document;
	var ss = doc.createElement( "link" );
	var ref;
	if( before ){
		ref = before;
	}
	else {
		var refs = ( doc.body || doc.getElementsByTagName( "head" )[ 0 ] ).childNodes;
		ref = refs[ refs.length - 1];
	}
	var sheets = doc.styleSheets;
	if( attributes ){
		for( var attributeName in attributes ){
			if( attributes.hasOwnProperty( attributeName ) ){
				ss.setAttribute( attributeName, attributes[attributeName] );
			}
		}
	}
	ss.rel = "stylesheet";
	ss.href = href;
	ss.media = "only x";
	function ready( cb ){
		if( doc.body ){
			return cb();
		}
		setTimeout(function(){
			ready( cb );
		});
	}
	ready( function(){
		ref.parentNode.insertBefore( ss, ( before ? ref : ref.nextSibling ) );
	});
	var onloadcssdefined = function( cb ){
		var resolvedHref = ss.href;
		var i = sheets.length;
		while( i-- ){
			if( sheets[ i ].href === resolvedHref ){
				return cb();
			}
		}
		setTimeout(function() {
			onloadcssdefined( cb );
		});
	};
	function loadCB(){
		if( ss.addEventListener ){
			ss.removeEventListener( "load", loadCB );
		}
		ss.media = media || "all";
	}
	if( ss.addEventListener ){
		ss.addEventListener( "load", loadCB);
	}
	ss.onloadcssdefined = onloadcssdefined;
	onloadcssdefined( loadCB );
	return ss;
};
</script>
<script>
  
  loadCSS("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.14/css/all.min.css", window.volantis.loadcss);
  
  
  
  
</script>
<!-- required -->

<script src="https://cdn.jsdelivr.net/npm/jquery@3.5/dist/jquery.min.js"></script>

<script>
  function pjax_fancybox() {
    $(".md .gallery").find("img").each(function () { //渲染 fancybox
      var element = document.createElement("a"); // a 标签
      $(element).attr("class", "fancybox");
      $(element).attr("pjax-fancybox", "");  // 过滤 pjax
      $(element).attr("href", $(this).attr("src"));
      if ($(this).attr("data-original")) {
        $(element).attr("href", $(this).attr("data-original"));
      }
      $(element).attr("data-fancybox", "images");
      var caption = "";   // 描述信息
      if ($(this).attr('alt')) {  // 判断当前页面是否存在描述信息
        $(element).attr('data-caption', $(this).attr('alt'));
        caption = $(this).attr('alt');
      }
      var div = document.createElement("div");
      $(div).addClass("fancybox");
      $(this).wrap(div); // 最外层套 div ，其实主要作用还是 class 样式
      var span = document.createElement("span");
      $(span).addClass("image-caption");
      $(span).text(caption); // 加描述
      $(this).after(span);  // 再套一层描述
      $(this).wrap(element);  // 最后套 a 标签
    })
    $(".md .gallery").find("img").fancybox({
      selector: '[data-fancybox="images"]',
      hash: false,
      loop: false,
      closeClick: true,
      helpers: {
        overlay: {closeClick: true}
      },
      buttons: [
        "zoom",
        "close"
      ]
    });
  };
  function SCload_fancybox() {
    if ($(".md .gallery").find("img").length == 0) return;
    loadCSS("https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css", document.getElementById("loadcss"));
    setTimeout(function() {
      loadScript('https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js', pjax_fancybox)
    }, 1);
  };
  $(function () {
    SCload_fancybox();
  });
</script>


<!-- internal -->







  <script defer src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script>
<script>
  // https://www.npmjs.com/package/vanilla-lazyload
  // Set the options globally
  // to make LazyLoad self-initialize
  window.lazyLoadOptions = {
    elements_selector: ".lazyload",
    threshold: 0
  };
  // Listen to the initialization event
  // and get the instance of LazyLoad
  window.addEventListener(
    "LazyLoad::Initialized",
    function (event) {
      window.lazyLoadInstance = event.detail.instance;
    },
    false
  );
  document.addEventListener('DOMContentLoaded', function () {
    lazyLoadInstance.update();
  });
  document.addEventListener('pjax:complete', function () {
    lazyLoadInstance.update();
  });
</script>




  
  
    <script>
      window.FPConfig = {
        delay: 0,
        ignoreKeywords: [],
        maxRPS: 5,
        hoverDelay: 25
      };
    </script>
    <script defer src="https://cdn.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"></script>
  




  <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
    var clipboard = new ClipboardJS('.btn-copy', {
        target: function (trigger) {
            return trigger.nextElementSibling
        }
    });
    function wait(callback, seconds) {
        var timelag = null;
        timelag = window.setTimeout(callback, seconds)
    }
    function pjax_initCopyCode() {
		if($(".highlight .code pre").length+$(".article pre code").length==0)return;
        var copyHtml = '';
        copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
        copyHtml += '<i class="fas fa-copy"></i><span>COPY</span>';
        copyHtml += '</button>';
        $(".highlight .code pre").before(copyHtml);
        $(".article pre code").before(copyHtml);
        clipboard.off('success').on('success', function (e) {
            let $btn = $(e.trigger);
            $btn.addClass('copied');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-check-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPIED';
            wait(function () {
                $icon.removeClass('fa-check-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        });
        clipboard.off('error').on('error', function (e) {
            e.clearSelection();
            let $btn = $(e.trigger);
            $btn.addClass('copy-failed');
            let $icon = $($btn.find('i'));
            $icon.removeClass('fa-copy');
            $icon.addClass('fa-times-circle');
            let $span = $($btn.find('span'));
            $span[0].innerText = 'COPY FAILED';
            wait(function () {
                $icon.removeClass('fa-times-circle');
                $icon.addClass('fa-copy');
                $span[0].innerText = 'COPY'
            }, 2000)
        })
    }
    $(function () {
        pjax_initCopyCode()
    });
</script>










  <script defer src="https://cdn.jsdelivr.net/gh/Schenk75/Source@master/tools/busuanzi.pure.mini.js" data-pjax></script>


  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/app.min.js"></script>




  
  
<script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.1.5/source/js/search.min.js"></script>

  


<!-- optional -->

  <script>
const SearchServiceimagePath="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@master/img/";
const ROOT =  ("/" || "/").endsWith('/') ? ("/" || "/") : ("//" || "/" );
function listenSearch(){
  
    customSearch = new HexoSearch({
      imagePath: SearchServiceimagePath
    });
  
}
document.addEventListener("DOMContentLoaded", listenSearch);

</script>











  <script defer>

  const LCCounter = {
    app_id: 'u9j57bwJod4EDmXWdxrwuqQT-MdYXbMMI',
    app_key: 'jfHtEKVE24j0IVCGHbvuFClp',
    custom_api_server: '',

    // 查询存储的记录
    getRecord(Counter, url, title) {
      return new Promise(function (resolve, reject) {
        Counter('get', '/classes/Counter?where=' + encodeURIComponent(JSON.stringify({url})))
          .then(resp => resp.json())
          .then(({results, code, error}) => {
            if (code === 401) {
              throw error;
            }
            if (results && results.length > 0) {
              var record = results[0];
              resolve(record);
            } else {
              Counter('post', '/classes/Counter', {url, title: title, times: 0})
                .then(resp => resp.json())
                .then((record, error) => {
                  if (error) {
                    throw error;
                  }
                  resolve(record);
                }).catch(error => {
                console.error('Failed to create', error);
                reject(error);
              });
            }
          }).catch((error) => {
          console.error('LeanCloud Counter Error:', error);
          reject(error);
        });
      })
    },

    // 发起自增请求
    increment(Counter, incrArr) {
      return new Promise(function (resolve, reject) {
        Counter('post', '/batch', {
          "requests": incrArr
        }).then((res) => {
          res = res.json();
          if (res.error) {
            throw res.error;
          }
          resolve(res);
        }).catch((error) => {
          console.error('Failed to save visitor count', error);
          reject(error);
        });
      });
    },

    // 构建自增请求体
    buildIncrement(objectId) {
      return {
        "method": "PUT",
        "path": `/1.1/classes/Counter/${ objectId }`,
        "body": {
          "times": {
            '__op': 'Increment',
            'amount': 1
          }
        }
      }
    },

    // 校验是否为有效的 UV
    validUV() {
      var key = 'LeanCloudUVTimestamp';
      var flag = localStorage.getItem(key);
      if (flag) {
        // 距离标记小于 24 小时则不计为 UV
        if (new Date().getTime() - parseInt(flag) <= 86400000) {
          return false;
        }
      }
      localStorage.setItem(key, new Date().getTime().toString());
      return true;
    },

    addCount(Counter) {
      var enableIncr = '' === 'true' && window.location.hostname !== 'localhost';
      enableIncr = true;
      var getterArr = [];
      var incrArr = [];
      // 请求 PV 并自增
      var pvCtn = document.querySelector('#lc-sv');
      if (pvCtn || enableIncr) {
        var pvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-sv', 'Visits').then((record) => {
          incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-sv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + 1;
              if (pvCtn) {
                pvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(pvGetter);
      }

      // 请求 UV 并自增
      var uvCtn = document.querySelector('#lc-uv');
      if (uvCtn || enableIncr) {
        var uvGetter = this.getRecord(Counter, 'http://example.com' + '/#lc-uv', 'Visitors').then((record) => {
          var vuv = this.validUV();
          vuv && incrArr.push(this.buildIncrement(record.objectId))
          var eles = document.querySelectorAll('#lc-uv #number');
          if (eles.length > 0) {
            eles.forEach((el,index,array)=>{
              el.innerText = record.times + (vuv ? 1 : 0);
              if (uvCtn) {
                uvCtn.style.display = 'inline';
              }
            })
          }
        });
        getterArr.push(uvGetter);
      }

      // 请求文章的浏览数，如果是当前页面就自增
      var allPV = document.querySelectorAll('#lc-pv');
      if (allPV.length > 0 || enableIncr) {
        for (i = 0; i < allPV.length; i++) {
          let pv = allPV[i];
          let title = pv.getAttribute('data-title');
          var url = 'http://example.com' + pv.getAttribute('data-path');
          if (url) {
            var viewGetter = this.getRecord(Counter, url, title).then((record) => {
              // 是当前页面就自增
              let curPath = window.location.pathname;
              if (curPath.includes('index.html')) {
                curPath = curPath.substring(0, curPath.lastIndexOf('index.html'));
              }
              if (pv.getAttribute('data-path') == curPath) {
                incrArr.push(this.buildIncrement(record.objectId));
              }
              if (pv) {
                var ele = pv.querySelector('#lc-pv #number');
                if (ele) {
                  if (pv.getAttribute('data-path') == curPath) {
                    ele.innerText = (record.times || 0) + 1;
                  } else {
                    ele.innerText = record.times || 0;
                  }
                  pv.style.display = 'inline';
                }
              }
            });
            getterArr.push(viewGetter);
          }
        }
      }

      // 如果启动计数自增，批量发起自增请求
      if (enableIncr) {
        Promise.all(getterArr).then(() => {
          incrArr.length > 0 && this.increment(Counter, incrArr);
        })
      }

    },


    fetchData(api_server) {
      var Counter = (method, url, data) => {
        return fetch(`${ api_server }/1.1${ url }`, {
          method,
          headers: {
            'X-LC-Id': this.app_id,
            'X-LC-Key': this.app_key,
            'Content-Type': 'application/json',
          },
          body: JSON.stringify(data)
        });
      };
      this.addCount(Counter);
    },

    refreshCounter() {
      var api_server = this.app_id.slice(-9) !== '-MdYXbMMI' ? this.custom_api_server : `https://${ this.app_id.slice(0, 8).toLowerCase() }.api.lncldglobal.com`;
      if (api_server) {
        this.fetchData(api_server);
      } else {
        fetch('https://app-router.leancloud.cn/2/route?appId=' + this.app_id)
          .then(resp => resp.json())
          .then(({api_server}) => {
            this.fetchData('https://' + api_server);
          });
      }
    }

  };

  LCCounter.refreshCounter();

  document.addEventListener('pjax:complete', function () {
    LCCounter.refreshCounter();
  });
</script>








<script>
function listennSidebarTOC() {
  const navItems = document.querySelectorAll(".toc li");
  if (!navItems.length) return;
  const sections = [...navItems].map((element) => {
    const link = element.querySelector(".toc-link");
    const target = document.getElementById(
      decodeURI(link.getAttribute("href")).replace("#", "")
    );
    link.addEventListener("click", (event) => {
      event.preventDefault();
      window.scrollTo({
		top: target.offsetTop + 100,
		
		behavior: "smooth"
		
	  });
    });
    return target;
  });

  function activateNavByIndex(target) {
    if (target.classList.contains("active-current")) return;

    document.querySelectorAll(".toc .active").forEach((element) => {
      element.classList.remove("active", "active-current");
    });
    target.classList.add("active", "active-current");
    let parent = target.parentNode;
    while (!parent.matches(".toc")) {
      if (parent.matches("li")) parent.classList.add("active");
      parent = parent.parentNode;
    }
  }

  function findIndex(entries) {
    let index = 0;
    let entry = entries[index];
    if (entry.boundingClientRect.top > 0) {
      index = sections.indexOf(entry.target);
      return index === 0 ? 0 : index - 1;
    }
    for (; index < entries.length; index++) {
      if (entries[index].boundingClientRect.top <= 0) {
        entry = entries[index];
      } else {
        return sections.indexOf(entry.target);
      }
    }
    return sections.indexOf(entry.target);
  }

  function createIntersectionObserver(marginTop) {
    marginTop = Math.floor(marginTop + 10000);
    let intersectionObserver = new IntersectionObserver(
      (entries, observe) => {
        let scrollHeight = document.documentElement.scrollHeight + 100;
        if (scrollHeight > marginTop) {
          observe.disconnect();
          createIntersectionObserver(scrollHeight);
          return;
        }
        let index = findIndex(entries);
        activateNavByIndex(navItems[index]);
      },
      {
        rootMargin: marginTop + "px 0px -100% 0px",
        threshold: 0,
      }
    );
    sections.forEach((element) => {
      element && intersectionObserver.observe(element);
    });
  }
  createIntersectionObserver(document.documentElement.scrollHeight);
}

document.addEventListener("DOMContentLoaded", listennSidebarTOC);
document.addEventListener("pjax:success", listennSidebarTOC);
</script>

<!-- more -->




    
      


<script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js"></script>


<script>
    var pjax;
    document.addEventListener('DOMContentLoaded', function () {
      pjax = new Pjax({
        elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox])',
        selectors: [
          "title",
          "#l_cover",
          "#pjax-container",
          "#pjax-header-nav-list"
        ],
        cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
        timeout: 5000
      });
    });

    document.addEventListener('pjax:send', function (e) {
      //window.stop(); // 相当于点击了浏览器的停止按钮

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = [""];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      window.subData = null; // 移除标题（用于一二级导航栏切换处）
      if (typeof $.fancybox != "undefined") {
        $.fancybox.close();    // 关闭弹窗
      }
      volantis.$switcher.removeClass('active'); // 关闭移动端激活的搜索框
      volantis.$header.removeClass('z_search-open'); // 关闭移动端激活的搜索框
      volantis.$wrapper.removeClass('sub'); // 跳转页面时关闭二级导航

      // 解绑事件 避免重复监听
      volantis.$topBtn.unbind('click');
      $('.menu a').unbind('click');
      $(window).unbind('resize');
      $(window).unbind('scroll');
      $(document).unbind('scroll');
      $(document).unbind('click');
      $('body').unbind('click');
	  
    });

    document.addEventListener('pjax:complete', function () {
      // 关于百度统计对 SPA 页面的处理：
      // 方案一：百度统计>管理>单页应用设置中，打开开启按钮即可对SPA进行统计。 https://tongji.baidu.com/web/help/article?id=324
      // 方案二：取消注释下列代码。 https://tongji.baidu.com/web/help/article?id=235
      // 

      // 关于谷歌统计对 SPA 页面的处理：
      // 当应用以动态方式加载内容并更新地址栏中的网址时，也应该更新通过 gtag.js 存储的网页网址。
      // https://developers.google.cn/analytics/devguides/collection/gtagjs/single-page-applications?hl=zh-cn
      

      $('.nav-main').find('.list-v').not('.menu-phone').removeAttr("style",""); // 移除小尾巴的移除
      $('.menu-phone.list-v').removeAttr("style",""); // 移除小尾巴的移除
      $('script[data-pjax], .pjax-reload script').each(function () {
        $(this).parent().append($(this).remove());
      });
      try{
          if (typeof $.fancybox == "undefined") {
            SCload_fancybox();
          } else {
            pjax_fancybox();
          }
        
        
        
        
        
          pjax_initCopyCode();
        
        
        
        
        
      } catch (e) {
        console.log(e);
      }
	  
    });

    document.addEventListener('pjax:error', function (e) {
	  
      window.location.href = e.triggerElement.href;
    });
</script>

    
  </div>
</body>
</html>
